import dayjs from 'dayjs'
import Koa, { Middleware } from 'koa'
import Router from 'koa-router'
import { createDBClient, insertDailyData } from '.'
import { chartsInterface, ClientInterface, DailyReportInterface, FaucetDataViews, FaucetInterface, FiveMinitesReportInterface, HourlyReportInterface, LastPaidInterface, ParamterInterface, ReportInterface } from '../model'
import { createMapData, getTime, initDataFaucet } from '../utils'


export async function createfaucetView(config: any): Promise<Middleware> {

    const clients = await createDBClient(config.config)

    const router = new Router()


    router.get("/", async (ctx: Koa.ParameterizedContext<Koa.DefaultState, Koa.DefaultContext, any>, next) => {

        let queryStr: any = JSON.stringify(ctx.query)
        queryStr = JSON.parse(queryStr)
        const { page = 1, size = 100 } = queryStr

        

        //查询
        let {view_datas,currency_set} = await query(clients, queryStr)
        //总页码
        const page_total = Math.ceil(view_datas.length / size)
        //总条数
        const total = view_datas.length

        //分页
        const strat = (page - 1) * size
        const end = strat + size
        view_datas = view_datas.slice(strat, end)

        //页码展示
        const { strat_page, end_page } = initPage(page, page_total)

        await ctx.render('index', {
            message: view_datas,
            total: total,
            view_total:total,
            page_total: page_total,
            current_page: page,
            current_size: size,
            start: strat_page,
            end: end_page,
            currency_set:currency_set
        })
    })


    router.get('/sort', async (ctx: Koa.ParameterizedContext<Koa.DefaultState, Koa.DefaultContext, any>, next) => {
        let queryStr: any = JSON.stringify(ctx.query)
        queryStr = JSON.parse(queryStr)
        const { page = 1, size = 100, sortName = '', order = '' } = queryStr

        let {view_datas,currency_set} = await query(clients, queryStr)
        const page_total = Math.ceil(view_datas.length / size)
        const total = view_datas.length

        //排序
        sort(sortName, order, view_datas)
        view_datas = order == 'DESC' ? view_datas.reverse() : view_datas
        //分页
        const strat = (page - 1) * size
        const end = strat + size

        view_datas = view_datas.slice(strat, end)

        const { strat_page, end_page } = initPage(page, page_total)

        await ctx.render('index', {
            message: view_datas,
            total: total,
            page_total: page_total,
            current_page: page,
            current_size: size,
            start: strat_page,
            end: end_page,
            currency_set:currency_set
        })
    });

    //按照货币类型查询
    router.get('/queryCondition', async (ctx: Koa.ParameterizedContext<Koa.DefaultState, Koa.DefaultContext, any>, next) => {

        let queryStr: any = JSON.stringify(ctx.query)
        queryStr = JSON.parse(queryStr)
        const { page = 1, size = 100, sortName = '', order = '' } = queryStr


        let {view_datas,currency_set} = await query(clients, queryStr)
        const page_total = Math.ceil(view_datas.length / size)
        const total = view_datas.length
        sort(sortName, order, view_datas)

        view_datas = order == 'DESC' ? view_datas.reverse() : view_datas

        const strat = (page - 1) * size
        const end = strat + size
        view_datas = view_datas.slice(strat, end)

        const { strat_page, end_page } = initPage(page, page_total)

        await ctx.render('index', {
            message: view_datas,
            total: total,
            page_total: page_total,
            current_page: page,
            current_size: size,
            start: strat_page,
            end: end_page,
            currency_set:currency_set
        })
    });

    router.get('/details/:id', async (ctx: Koa.ParameterizedContext<Koa.DefaultState, Koa.DefaultContext, any>, next) => {
        const queryStr = ctx.querystring
        const id: number = ctx.params.id

        const basicMsg = new Map<string, any>()
        const faucet_map = new Map<string, FaucetDataViews>()

        const other_faucet = new Map<string, FaucetInterface>()
        let past_hours: number = 0
        let past_daily: number = 0
        let past_week: number = 0
        let last_pay: number[] = []


        let {view_datas,currency_set} = await query(clients, {})

        view_datas = view_datas.filter((item) => {
            return item.id == id
        })

        for (const item of view_datas) {
            past_hours += item.paid_hour
            past_daily += item.paid_day
            past_week += item.paid_week
            last_pay.push(item.lastPayment)
        }
        const otherFaucet = await clients.faucetClient.getMany({ condition: { "owner_name": view_datas[0].owner_user, "name": { $ne: view_datas[0].name } } })
        for (const item of otherFaucet) {
            other_faucet.set(item.name, item)
        }
        const dates = new Date().getTime() - new Date(view_datas[0].createTime).getTime()
        const createTime = dates / (1 * 24 * 60 * 60 * 1000)
        basicMsg.set("past_hour", past_hours)
        basicMsg.set("past_daily", past_daily)
        basicMsg.set("past_week", past_week)
        basicMsg.set("owner_name", view_datas[0].owner_user)
        basicMsg.set("active_users", view_datas[0].active_users)
        basicMsg.set("other_faucet", other_faucet)
        basicMsg.set("detailsName", view_datas[0].name)
        basicMsg.set("faucetTime", Math.floor(createTime))
        basicMsg.set("createTime", view_datas[0].createTime)
        basicMsg.set("last_pay", last_pay[0])
        await ctx.render('details', { faucet_datas: view_datas, basic: basicMsg })
    });





    router.get('/chart', async (ctx: Koa.ParameterizedContext<Koa.DefaultState, Koa.DefaultContext, any>, next) => {


        let queryStr: any = JSON.stringify(ctx.query)
        const hour_time = new Set<string>()
        const daily_time= new Set<string>()
        queryStr = JSON.parse(queryStr)
        const { id } = queryStr

        const { last_day, last_month } = getTime()

        const faucet_datas = await clients.faucetClient.getMany({ condition: { id: id, balance: { $ne: "0.00000000" } } })
        const hour_datas = await clients.hourClient.getMany({ condition: { timezone: { $gt: String(last_day) } } })
        const day_datas = await clients.dailyClient.getMany({ condition: { timezone: { $gt: String(last_month) } } })
        hour_datas.map((item)=>{
            
            hour_time.add(dayjs.unix(Number(item.timezone)).format('YYYY-MM-DD HH')+'点')
        })
        day_datas.map((item)=>{
            daily_time.add(dayjs.unix(Number(item.timezone)).format('YYYY-MM-DD'))
        })
        console.log(Array.from(hour_time))
        console.log(daily_time)
        const daily_charts: chartsInterface[] = initChart(faucet_datas, hour_datas)
        const month_charts: chartsInterface[] = initChart(faucet_datas, day_datas)

        ctx.body = [daily_charts, month_charts,Array.from(hour_time),Array.from(daily_time)]
    });




    const ret = router.routes()
    return ret as Middleware
}


export async function query(clients: ClientInterface, req: { currencyName?: string, name?: string }) {
    return await initDBFaucetData(clients, req)
}


export async function initDBFaucetData(clients: ClientInterface, req: { currencyName?: string, name?: string }) {
    const start_time = new Date().getTime()
    const view_datas: FaucetDataViews[] = new Array();
    const week_map: Map<string, number> = new Map()
    const { currencyName = '', name = '' } = req


    const { now_hour, now_day, now_week } = getTime();



    let faucet_datas: FaucetInterface[] = []
    let condition: object = { balance: { $ne: "0.00000000" }, name: { $regex: name } }

    if (currencyName != '')
        condition = { balance: { $ne: "0.00000000" }, currency: currencyName, name: { $regex: name } }

    faucet_datas = await clients.faucetClient.getMany({ condition: condition })
    const last_datas = await clients.lastClient.getMany({})
    const hour_datas = await clients.hourClient.getMany({ condition: { "timezone": String(now_hour) } })
    const daily_datas = await clients.dailyClient.getMany({ condition: { "timezone": String(now_day) } })
    const week_datas = await clients.dailyClient.getMany({ condition: { "timezone": { $gt: String(now_week) } } })
    const hour_map = createMapData(hour_datas)
    const daily_map = createMapData(daily_datas)
    const last_map = createMapData(last_datas)


    week_datas.map((item) => {
        let total: number = week_map.get(item.faucet_id) || 0
        total += Number(item.total)
        week_map.set(item.faucet_id, total)
    })

    const currency_set  = new Set<string>()
    faucet_datas.map((faucet) => {
        let hour = hour_map.get(faucet._id)
        let daily = daily_map.get(faucet._id)
        let last = last_map.get(faucet._id)
        let week = week_map.get(faucet._id)
        currency_set.add(faucet.currency)
        view_datas.push(
            {
                _id: faucet._id,
                name: faucet.name,
                id: Number(faucet.id),
                url: faucet.url,
                currency: faucet.currency,
                lastPayment: last?.last_paid_mins || 0,
                balance: (faucet.balance) + '',
                paid_hour: hour?.total || 0,
                paid_day: daily?.total || 0,
                createTime: dayjs.unix(Number(faucet.timezone)).format('YYYY-MM-DD'),
                paid_week: week || 0,
                owner_user: faucet.owner_name,
                active_users: faucet.active_users
            }
        )
    })
    console.log(`query时间：${new Date().getTime() - start_time}`)
    return {
        view_datas,
        currency_set
    }
}



export function initParamter(query: string) {

    query = JSON.parse(query)

}

export function sort(sortName: string, order: string, view_data: FaucetDataViews[]) {

    if (sortName == 'last_payment' && order != 'NORMAL') {
        view_data.sort((a, b) => {
            return a.lastPayment - b.lastPayment
        })
    }
    if (sortName == 'hour_paid' && order != 'NORMAL') {
        view_data.sort((a, b) => {
            return a.paid_hour - b.paid_hour
        })
    }
    if (sortName == 'daily_paid' && order != 'NORMAL') {
        view_data.sort((a, b) => {
            return a.paid_day - b.paid_day
        })
    }
}


export function initPage(current_page: number, page_total: number) {
    let strat_page: number = 1
    let end_page: number = 7
    end_page = end_page > page_total ? page_total : 7
    if (current_page / 4 > 1) {
        end_page = Number(current_page) + 3
        strat_page = Number(current_page) - 3
        if (end_page > page_total) {
            strat_page -= (end_page - page_total)
            end_page = page_total
        }
    }


    return {
        strat_page, end_page
    }
}


/**
 * 每种货币都有24条数据，但是主键是相同。
 * 
 * view_data：经过id筛选后的faucet集合数据
 * hour_datas：24小时之前的hour_report集合数据
 * 需要取出的数据为：货币种类和当前货币种类的24小时total
 * 循环view_data，hour_datas使用fliter方法去判断是否满足条件（view_data的主键等于hour_datas的外键）。
 *      满足条件时：将当前这条数据的total放入数组中
 *      不满足即退出
 */
export function initChart(faucet_datas: FaucetInterface[], initDatas: ReportInterface[]) {

    const return_map = new Map<string, number[]>()
    const charts: chartsInterface[] = []

    for (const item of faucet_datas) {
        let total: number[] = []
        const arr = initDatas.filter((value) => {
            if (value.faucet_id == item._id) {
                total.push(value.total)
                return true
            }
            return false
        })
        return_map.set(item.currency, total)
    }


    for (const item of return_map.keys()) {

        charts.push(
            {
                name: item,
                type: "line",
                stack: '总量',
                data: return_map.get(item) || []
            }
        )

    }
    const time = return_map.get('time')
    return charts
}